#ifndef RECT_HPP_INCLUDED
#define RECT_HPP_INCLUDED

#include <cmath>
#include <algorithm>
#include "Vector.hpp"

/**	 Cool VES Math */
namespace cvMath
{
	// General Rectangle class template
	template<typename T> class Rect
	{
		public:
			T l, r, t, b;
			Rect<T>();
			Rect<T>(const T left, const T right, const T top, const T bottom);
			template<typename J> Rect<T>(const Rect<J> & copy);
			Rect<T>& operator=	(const Rect<T> & copy);
	};

	// Operators
	template<typename T> Rect<T> operator+	(const Rect<T> &leftRect, const Rect<T> &rightRect);
	template<typename T> Rect<T> operator-	(const Rect<T> &leftRect, const Rect<T> &rightRect);
	template<typename T> Rect<T> operator*	(const Rect<T> &leftRect, const T realVal);
	template<typename T> Rect<T> operator/	(const Rect<T> &leftRect, const T realVal);

	// Assingment operators
	template<typename T> Rect<T>& operator+=	(Rect<T> &leftRect, const Rect<T> &rightRect);
	template<typename T> Rect<T>& operator-=	(Rect<T> &leftRect, const Rect<T> &rightRect);
	template<typename T> Rect<T>& operator*=	(Rect<T> &leftRect, const T realVal);
	template<typename T> Rect<T>& operator/=	(Rect<T> &leftRect, const T realVal);

	// Calculates Rectangle's corner vectors.
	template<typename T> void rectCorners(const Rect<T> & rect, Vec2<T> * vlt, Vec2<T> * vrt, Vec2<T> * vrb, Vec2<T> * vlb);

	// Returns Rect rotated around point by angle.
	template<typename T> Rect<T> rotateRect(const Rect<T> & rect, const Vec2<T> & offset, T angle);

	// Returns Rect moved by vector
	template<typename T> Rect<T> offsetRect(const Rect<T> & rect, const Vec2<T> & offset);

	// Expands rect by point
	template<typename T> Rect<T> expandRect(const Rect<T> &rectA, const Vec2<T> &point);

	// Combines two rects (union)
	template<typename T> Rect<T> unionRects(const Rect<T> & rectA, const Rect<T> & rectB);

	// Intersects two rects
	template<typename T> Rect<T> intersectRects(const Rect<T> & rectA, const Rect<T> & rectB);

	// Rect width & height. Rect is invalid when width or height is below zero.
	template<typename T> T rectWidth(const Rect<T> & rect);
	template<typename T> T rectHeight(const Rect<T> & rect);

	// Tests if vector (point) is contained by the rect.
	template<typename T> bool rectContains(const Rect<T> & rect, const Vec2<T> & p);

	// Tests if a rect is completly contained by another rect.
	template<typename T> bool rectContains(const Rect<T> & outer, const Rect<T> & inner);

	// Test if rects intersect. (rectB's corners are tested first against rectA)
	template<typename T> bool rectIntersect(const Rect<T> & rectA, const Rect<T> & rectB);

/// TEMPLATE IMPLEMENTATION...
#include "../../impl/Math/Rect.inl"

	// Common rect types
	typedef Rect<float> Rectf;
	typedef Rect<double> Rectd;
	typedef Rect<int>	Recti;

}; // end of namespace cvMath

#endif // RECT_HPP_INCLUDED
